#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/event.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "macros.h"
#include "user.h"

int listener = 0;
char recvbuf[MAX_RECV_BUFF];

void handle_event(int kq, struct kevent* events, int n);
void enqueue(const char * buf, int bytes);
void receive(int fd, int availbyte);
void accept_new(int kq, int data);

int create_listener()
{
	int sofd = socket(PF_INET, SOCK_STREAM, 0);
	printf("sofd=%d\n", sofd);
	if(sofd == -1)
	{
		printf("create socket error sofd=%d\n", sofd);
		return -1;
	}
	listener = sofd;
	struct sockaddr_in myaddr;
	myaddr.sin_family = AF_INET;
	myaddr.sin_port = htons(LISTEN_PORT); 
	myaddr.sin_addr.s_addr = inet_addr("192.168.10.104");
	bzero(&(myaddr.sin_zero), 8);
	//printf("bind ip=%s", inet_ntoa(myaddr.sin_addr));
	//return;
	int ret = bind(sofd, &myaddr, sizeof(myaddr));
	if(ret == -1)
	{
		printf("bind failed! \n");
		return -1;
	}
	printf("bind ok!\n");
	if(listen(sofd, MAX_LISTEN_CN) == -1)
	{
		printf("listen error!\n");
		return -1;
	}
	return sofd;
}

int register_queue(int kq, int fd)
{
	struct kevent changes[1];
	EV_SET(&changes, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
	int ret = kevent(kq, changes, 1, NULL, 0, NULL);
	if(ret == -1)
	{
		return 0;
	}
	return 1;
}

void wait_event(int kq)
{
	struct kevent events[MAX_EVENT_COUNT];
	printf("start_waiting events!\n");
	while(1)
	{
		int ret = kevent(kq, NULL, 0, events, MAX_EVENT_COUNT, NULL);
		if(ret == -1)
		{
			printf("kevent failed!\n");
			continue;
		}
		handle_event(kq, events, ret);
	}
}

void handle_event(int kq, struct kevent* events, int n)
{
	int i;
	printf("handle event n=%d\n", n);
	for(i = 0; i < n; i++)
	{
		int sofd = events[i].ident;
		int data = events[i].data;
		printf("event ident=%d data=%d\n", sofd, data);
		if(sofd == listener)
		{
			accept_new(kq, data);
		}
		else
		{
			receive(sofd, data);
		}
	}
}

void accept_new(int kq, int data)
{
	int i;
	for(i = 0; i < data; i++)
	{
		struct sockaddr_in clientaddr;
		int len = sizeof(clientaddr);
		//int client = accept(listener, &clientaddr, sizeof(struct sockaddr_in));
		int client = accept(listener, &clientaddr, &len);
		if(client == -1)
		{
			printf("accept error!\n");
			continue;
		}
		printf("receive new fd=%d addr=%s port=%d\n", client,
				inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
		if(!register_queue(kq, client))
		{
			printf("new user register error!\n");
			continue;
		}
	}
}

void receive(int fd, int availbyte)
{
	int bytes = recv(fd, recvbuf, availbyte, 0);
	if(bytes == 0 || bytes == -1)
	{
		close(fd);
		printf("recv error from %d\n", fd);
		return;
	}
	enqueue(recvbuf, bytes);
}

void enqueue(const char * buf, int bytes)
{
	printf("recv datasize=%d \n", bytes);
	return;
}

int main(int argc, char * argv)
{
	printf("start ser...\n");
	int sofd = create_listener();
	if(sofd == -1)
	{
		return -1;
	}
	init_userlist();
	user_data ud;
	//printf("fd=%d uid=%d name=%s\n", ud.fd, ud.uid, ud.name);
	int kq = kqueue();
	register_queue(kq, sofd);
	printf("init queue!\n");
	wait_event(kq);
	return 0;
}
